package io.arukas.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

/**
 * Created by IntelliJ IDEA. <br/>
 * Author: YuXian Niu <br/>
 * Email: niuyuxian@163.com <br/>
 * Create: 2021-08-15 21:47 <br/>
 */
@EnableWebSecurity
public class WebSecurityConfig {

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder(11);
    }


    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth
                .inMemoryAuthentication()
                .withUser("admin").password(passwordEncoder().encode("admin")).roles("ADMIN");
    }


    @Order(1)
    @Configuration
    public static class AdminWebSecurityConfigurer extends WebSecurityConfigurerAdapter {

        private final Logger logger = LoggerFactory.getLogger(getClass());

        @Autowired
        private PasswordEncoder passwordEncoder;

        @Override
        public void configure(WebSecurity web) throws Exception {
            super.configure(web);
        }

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            logger.debug("----------------AdminWebSecurityConfigurer#HttpSecurity----------------");
            http
                    .csrf().disable()
                    .antMatcher("/admin/**")
                    .authorizeRequests()
                    .antMatchers("/admin/login").permitAll()
                    .anyRequest().authenticated()


                    .and()
                    // get注销时需 http.csrf().disable()
                    .formLogin().loginPage("/admin/login")
                    .failureUrl("/admin/login?error=true")
                    .loginProcessingUrl("/admin/login")
                    .defaultSuccessUrl("/admin/page", true).permitAll()
                    //.failureHandler(authenctiationFailureHandler)
                    .and()
                    .logout().logoutUrl("/admin/logout").logoutSuccessUrl("/")
                    .and()
                    .exceptionHandling()
                    .accessDeniedPage("/403")
            ;
        }
    }

    @Order(2)
    @Configuration
    public static class UserWebSecurityConfigurer extends WebSecurityConfigurerAdapter {

        private final Logger logger = LoggerFactory.getLogger(getClass());

        @Autowired
        private PasswordEncoder passwordEncoder;

        @Override
        public void configure(WebSecurity web) throws Exception {
            //web.ignoring().antMatchers("/account/**");
        }

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            logger.debug("----------------UserWebSecurityConfigurer#HttpSecurity----------------");

            http
                    .csrf().disable()
                    .antMatcher("/user/**")
//                    .antMatcher("/**")
                    .authorizeRequests()
                    .antMatchers("/user/login").permitAll()
                    .antMatchers("/guest/**").permitAll()
                    .anyRequest().authenticated()


                    .and()
                    // get注销时需 http.csrf().disable()
                    .formLogin().loginPage("/user/login")
                    .failureUrl("/user/login?error=true")
                    .loginProcessingUrl("/user/login")
                    .defaultSuccessUrl("/user/page", true).permitAll()

                    .and()
                    .logout().logoutUrl("/user/logout").logoutSuccessUrl("/")
                    .and()
                    .exceptionHandling().accessDeniedPage("/403")

            ;

        }

        //这里的配置会覆盖 configureGlobal()中的配置.
        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            logger.debug("----------------UserWebSecurityConfigurer#AuthenticationManagerBuilder----------------");
            auth
                    .inMemoryAuthentication()
                    .withUser("user").password(passwordEncoder.encode("user")).roles("USER");
        }
    }

    // 无序的最后执行
    @Configuration
    public static class OtherWebSecurityConfigurer extends WebSecurityConfigurerAdapter {

        private final Logger logger = LoggerFactory.getLogger(getClass());

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            logger.debug("----------------OtherWebSecurityConfigurerr#HttpSecurity----------------");

            // 其它地址放行
            http.csrf().disable().antMatcher("/**").authorizeRequests().anyRequest().permitAll();
        }
    }
}
